<?php
/**
 * Created by PhpStorm.
 * Author: sitewang@aliyun.com
 * CreateTime: 2022/09/26 2022/9/26
 * Blog：www.myblogs.xyz
 */

namespace app\infrastructure\utils;

class Identity
{
    protected $identityCardNumber;

    public function __construct(string $identityCardNumber)
    {
        $identityCardNumber = str_replace(' ', '', $identityCardNumber);
        $identityCardNumber = str_replace('-', '', $identityCardNumber);
        $identityCardNumber = str_replace('_', '', $identityCardNumber);
        $this->identityCardNumber = strtoupper($identityCardNumber);
    }

    /**
     * Check The ID Card is legal.
     *
     * @return bool
     * @author Seven Du <shiweidu@outlook.com>
     */
    public function legal(): bool
    {
        $regionCode = (int) substr($this->identityCardNumber, 0, 6);

        return ($regionCode >= 110000
            && $regionCode <= 820000
            && checkdate(
                intval(substr($this->identityCardNumber, 10, 2)),
                intval(substr($this->identityCardNumber, 12, 2)),
                intval(substr($this->identityCardNumber, 6, 4))
            )
            && $this->validateCheckCode()
        );
    }

    /**
     * Get The ID Card People Birthday.
     *
     * @return string
     * @author Seven Du <shiweidu@outlook.com>
     */
    public function birthday(): string
    {
        $year = substr($this->identityCardNumber, 6, 4);
        $month = substr($this->identityCardNumber, 10, 2);
        $day = substr($this->identityCardNumber, 12, 2);

        return sprintf('%s-%s-%s', $year, $month, $day);
    }

    /**
     * Get the ID Card People Gender.
     *
     * @return string
     * @author Seven Du <shiweidu@outlook.com>
     */
    public function gender(): string
    {
        return ((intval(substr($this->identityCardNumber, 16, 1)) % 2) === 0) ? '女' : '男';
    }

    /**
     * Get the ID Card People Age.
     *
     * @return int
     */
    public function age(): int
    {
        # 获得出生年月日的时间戳
        $date = strtotime(substr($this->identityCardNumber, 6, 8));
        # 获得今日的时间戳
        $today = strtotime('today');
        # 得到两个日期相差的大体年数
        $diff = floor(($today-$date) / 86400 / 365);
        # 加上这个年数后得到那日的时间戳后与今日的时间戳相比
        $age = strtotime(substr($this->identityCardNumber, 6, 8) . ' +' . $diff . 'years') > $today ? ($diff+1) : $diff;
        return intval($age);
    }

    /**
     * PHP根据身份证号，自动获取对应的星座函数
     *
     * @return string
     */
    public function constellation(): string
    {
        $bir = substr($this->identityCardNumber,10,4);
        $month = (int)substr($bir,0,2);
        $day = (int)substr($bir,2);
        $strValue = '';
        if (($month == 1 && $day >= 20) || ($month == 2 && $day <= 18)) {
            $strValue = '水瓶座';
        } else if (($month == 2 && $day >= 19) || ($month == 3 && $day <= 20)) {
            $strValue = '双鱼座';
        } else if (($month == 3 && $day > 20) || ($month == 4 && $day <= 19)) {
            $strValue = '白羊座';
        } else if (($month == 4 && $day >= 20) || ($month == 5 && $day <= 20)) {
            $strValue = '金牛座';
        } else if (($month == 5 && $day >= 21) || ($month == 6 && $day <= 21)) {
            $strValue = '双子座';
        } else if (($month == 6 && $day > 21) || ($month == 7 && $day <= 22)) {
            $strValue = '巨蟹座';
        } else if (($month == 7 && $day > 22) || ($month == 8 && $day <= 22)) {
            $strValue = '狮子座';
        } else if (($month == 8 && $day >= 23) || ($month == 9 && $day <= 22)) {
            $strValue = '处女座';
        } else if (($month == 9 && $day >= 23) || ($month == 10 && $day <= 23)) {
            $strValue = '天秤座';
        } else if (($month == 10 && $day > 23) || ($month == 11 && $day <= 22)) {
            $strValue = '天蝎座';
        } else if (($month == 11 && $day > 22) || ($month == 12 && $day <= 21)) {
            $strValue = '射手座';
        } else if (($month == 12 && $day > 21) || ($month == 1 && $day <= 19)) {
            $strValue = '魔羯座';
        }
        return $strValue;
    }

    /**
     * 根据身份证号，自动返回对应的生肖
     *
     * @return string
     */
    public function zodiac(): string
    {
        $start = 1901;
        $end = (int)substr($this->identityCardNumber,6,4);
        $x = ($start - $end) % 12;
        $value = '';
        if ($x == 1 || $x == -11) {$value = '鼠';}
        if ($x == 0) { $value = '牛';}
        if ($x == 11 || $x == -1) {$value = '虎';}
        if ($x == 10 || $x == -2) {$value = '兔';}
        if ($x == 9 || $x == -3) {$value = '龙';}
        if ($x == 8 || $x == -4) {$value = '蛇';}
        if ($x == 7 || $x == -5) {$value = '马';}
        if ($x == 6 || $x == -6) {$value = '羊';}
        if ($x == 5 || $x == -7) {$value = '猴';}
        if ($x == 4 || $x == -8) {$value = '鸡';}
        if ($x == 3 || $x == -9) {$value = '狗';}
        if ($x == 2 || $x == -10) {$value = '猪';}
        return $value;
    }

    public function validateCheckCode(): bool
    {
        // Init
        $identityCardNumber = $this->identityCardNumber;
        $index = $sum = 0;

        // Calculation $sum
        for ($index; $index < 17; $index++) {
            $sum += ((1 << (17 - $index)) % 11) * intval(substr($identityCardNumber, $index, 1));
        }

        // Calculation $quotiety
        $quotiety = (12 - ($sum % 11)) % 11;

        if ($quotiety < 10) {
            return intval(substr($identityCardNumber, 17, 1)) === $quotiety;
        }

        return $quotiety === 10;
    }
}